package top.v5it.japi.ddd.spring.boot.autoconfigure;

import cn.hutool.core.lang.Snowflake;
import cn.hutool.core.util.IdUtil;
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
import org.springframework.boot.autoconfigure.data.redis.RedisProperties;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Import;
import org.springframework.data.redis.connection.RedisConnectionFactory;
import org.springframework.data.redis.core.RedisOperations;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.jdbc.core.namedparam.NamedParameterJdbcTemplate;
import top.v5it.japi.ddd.core.cache.BasicCache;
import top.v5it.japi.ddd.core.cache.RedisCache;
import top.v5it.japi.ddd.core.config.JapiDddAutoConfiguration;
import top.v5it.japi.ddd.core.dao.BasicDao;
import top.v5it.japi.ddd.core.dao.impl.BasicDaoJdbcImpl;
import top.v5it.japi.ddd.core.dao.impl.factory.VObjFactory;
import top.v5it.japi.ddd.core.dao.impl.mybatis.GenericDao;
import top.v5it.japi.ddd.core.repository.CacheEntityDao;
import top.v5it.japi.ddd.core.repository.Repository;
import top.v5it.japi.ddd.spring.boot.autoconfigure.properties.JapiDddProperties;

/**
 * @author zhanpu
 * @date 2023/3/24
 */
@EnableConfigurationProperties(JapiDddProperties.class)
@Import({JapiDddAutoConfiguration.class, ValidatorConfiguration.class})
@Configuration
public class JapiDddAutoConfigure {

    @Configuration
    @ConditionalOnClass(RedisOperations.class)
    @EnableConfigurationProperties(RedisProperties.class)
    static class RedisConfig {

        @Bean
        RedisTemplate<String, Object> redisTemplate(RedisConnectionFactory factory) {
            RedisTemplate<String, Object> template = new RedisTemplate<>();
            template.setConnectionFactory(factory);
            return template;
        }

        @Bean
        BasicCache redisCache(RedisTemplate<String, Object> redisTemplate) {
            return new RedisCache(redisTemplate);
        }
    }

    @Bean
    VObjFactory vObjFactory(JapiDddProperties japiDddProperties) {
        return new VObjFactory(japiDddProperties.getVObjFilepath());
    }

    /**
     * @param dao {@link GenericDao}
     * @return {@link BasicDaoJdbcImpl}
     */
    @Bean
    BasicDaoJdbcImpl basicDao(GenericDao dao, NamedParameterJdbcTemplate jdbcTemplate) {
        return new BasicDaoJdbcImpl(dao, jdbcTemplate);
    }

    /**
     * @param basicDao {@link BasicDao}
     * @return {@link Repository}
     */
    @Bean
    Repository repository(BasicDao basicDao) {
        final Repository repository = new Repository();
        repository.setDao(basicDao);
        return repository;
    }

    /**
     * @param repository {@link Repository}
     * @param basicCache {@link RedisCache}
     * @return {@link CacheEntityDao}
     */
    @Bean
    CacheEntityDao repositoryWithCache(BasicDao basicDao, BasicCache basicCache) {
        final CacheEntityDao cacheEntityDao = new CacheEntityDao();
        cacheEntityDao.setDao(basicDao);
        cacheEntityDao.setCache(basicCache);
        return cacheEntityDao;
    }

    /**
     * id生成
     *
     * @param japiDddProperties
     * @return
     */
    @Bean
    Snowflake snowflake(JapiDddProperties japiDddProperties) {
        return IdUtil.getSnowflake(japiDddProperties.getWorkerId(), japiDddProperties.getDatacenterId());
    }

}
